﻿/**
 * Trabalho elaborado por Alexandre Leitão, aluno nº 10331
 * e
 * Pedro Lemos Figueiredo, aluno nº 10326
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace eda1314_10331_10326
{
    /// <summary>
    /// Classe responsável por mexer em código da janela form1
    /// </summary>
    public partial class Form1 : Form
    {
        public int[,] grayMap;
        Bitmap img = null;
        public GraphForm GForm = new GraphForm();
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// Carrega uma imagem e mete-a na picture box
        /// </summary>
        /// <param name="sender">Objeto que indica que ação foi tomada</param>
        /// <param name="e">Guarda a informação de quando o rato é clicado em cima do botão</param>
        private void LoadButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog openImageFile = new OpenFileDialog();
            openImageFile.Title = "Load Image";
           /* openImageFile.Filter = "BitMapBitmap Files (*.bmp;*.dib)|*.bmp;*.dib|JPEG(*.jpg;*.jpeg;*.jpe;*.jfif)" +
              "|*.jpg;*.jpeg;*.jpe;*.jfif|GIF(*.gif)|*.gif|TIFF(*.tif;*.tiff)|*.tif;*.tiff|PNG(*.png)|*.png|" +
              "ICO(*.ico)|*.ico|All Pictures Files|*.bmp;*.dib;*.jpg;*.jpeg;*.jpe;*.jfif;*.gif;*.tif;*.tiff;" +
              "*.png;*.ico";*/
            String path;
            MemoryStream stream;
            // openImageFile.FilterIndex = INDEX_OPEN;
            openImageFile.RestoreDirectory = true;
            if (openImageFile.ShowDialog() == DialogResult.OK)
            {
                path = openImageFile.FileName;
                PGM image = new PGM(path);
                image.Read();
                this.pictureBox.Image = PGM.CreateBitmap(image);
                stream = new MemoryStream(File.ReadAllBytes(path));
                this.pictureBox.Image = this.makeImage(stream);
            }
        }
        /// <summary>
        /// Lê a imagem como uma Stream de modo a gravá-la numa bitmap pixel a pixel
        /// </summary>
        /// <param name="stream">Contém os dados de uma imagem</param>
        /// <returns></returns>
        private Bitmap makeImage(MemoryStream stream)
        {
            int width = 0;
            int height = 0;
            int lines = 0;
            int counterX = 0;
            int counterY = 0;
            int counter = 0;
            List<String> image = new List<String>();
            using (var reader = new StreamReader(stream, Encoding.ASCII) )
            {
                string line;
                while((line = reader.ReadLine()) != null)
                {
                    if (lines == 2)
                    {  
                        string[] size = line.Split(' ');
                        width = Int16.Parse(size[0]);
                        height = Int16.Parse(size[1]);
                        this.grayMap = new int[width,height];

                        img = new Bitmap(width, height, PixelFormat.Format32bppArgb);

                    }
                    else if(lines > 3 && lines < (width*height))
                    {
                       
                        if ((lines - 4) / width == 0)
                        {
                            Color gray = Color.FromArgb(Int16.Parse(line), Int16.Parse(line), Int16.Parse(line));
                            this.grayMap[counterX, counterY] = Int16.Parse(line);
                            img.SetPixel(counterX, counterY, gray);
                            counterX++;
                            counter++;
                        }
                        else if ((lines - 4) % width == 0 && (lines - 4) / width != 0)
                        {
                            counterX = 0;
                            counterY++;
                        }
                        else
                        {
                            Color gray = Color.FromArgb(Int16.Parse(line), Int16.Parse(line), Int16.Parse(line));
                            grayMap[counterX, counterY] = Int16.Parse(line);
                            img.SetPixel(counterX, counterY, gray);
                            counterX++;
                            counter++;
                        }
                    }
                    lines++;
                }
            }
            return img;
        }
        /// <summary>
        /// Cria um gráfico que demonstra os valores temporais do algoritmo a* a correr
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="gray"></param>
        //private void imageGraphic(int x, int y, int gray)
        //{
        //    Console.Write(x + "__" + y);
        //    using(Graphics gfx = Graphics.FromImage(this.pictureBox.BackgroundImage))
        //    using(SolidBrush brush = new SolidBrush(Color.FromArgb(gray, gray, gray)))
        //    {
        //        gfx.FillRectangle(brush, x, y, 1, 1);
        //    }
        //}
        /// <summary>
        /// Faz com que o método do algoritmo seja corrido com os valores corretos
        /// </summary>
        /// <param name="sender">Objeto que indica que ação foi tomada</param>
        /// <param name="e">Guarda a informação de quando o rato é clicado em cima do botão</param>
        private void RunAlgorithm_Click(object sender, EventArgs e)
        {
            ///Watch resposible for measuring the algorithm running time
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();

            ///Initialization of the start and end points
            ///Initialization of the A* algorithm(Pathfinder)
            
            Point start = new Point(192, 48);
            Point end = new Point(260, 508);
            PathFinder star = new PathFinder();

            ///Running the algorithm and measuring the time
            
            watch.Start();
            List<Point> path = star.Algorithm(start, end, this.grayMap, this.img);
            watch.Stop();

            ///Section responsible for dealing with the statistics
            ///given by the watchs
            
            double time1 = Int64.Parse(watch.ElapsedMilliseconds.ToString());
            this.comboBox1.Items.Add((time1 / 1000));
            this.comboBox1.Text = this.comboBox1.Items[this.comboBox1.Items.IndexOf((time1 / 1000))].ToString(); 

            double time3 = 0;
            foreach (double value in this.comboBox1.Items)
            {
                
                time3 += value;
            }
            this.label1.Text = Math.Round(time3 / this.comboBox1.Items.Count, 4).ToString();
          
            /*
            double time2 = 0;
            foreach(double value in star.getTimeList())
            {
                time2 += value;
            }
            time2 = ((time2 / star.getTimeList().Count) * 1000);
            this.label8.Text = Math.Round( time2, 4 ).ToString();
            */

            this.label2.Text = path.Count.ToString();
            this.createTextFile(path);
            this.actualizeGraph((time1 / 1000) /*, time2 */);
            this.GForm.Show();
            
            this.pictureBox.Image = this.img;
        }
        /// <summary>
        /// Atualiza o gráfico
        /// </summary>
        /// <param name="data1">Tempo de execução do algoritmo</param>
        private void actualizeGraph(double data1 /* , double data2 */)
        {
            this.GForm.chart1.Show();
            /*this.GForm.chart2.Show();*/
            this.GForm.chart1.Series["Time"].Points.Add(data1);
            /*this.GForm.chart2.Series["Time"].Points.Add(data2);*/
            
        }
        /// <summary>
        /// Cria um ficheiro tzt com dados do caminho percorrido
        /// </summary>
        /// <param name="path">Lista de ontos percorridos</param>
        private void createTextFile(List<Point> path)
        {
            string filePath = String.Format(@"{0}\List_of_points.txt", Application.StartupPath);
            Console.WriteLine(filePath);
            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filePath))
            {
                foreach (Point pt in path)
                {
                    sw.WriteLine(pt.ToString());
                }
            }
            
        }
    }
}